package com.xdhl.fu.member.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xdhl.fu.common.core.constant.CacheConstants;
import com.xdhl.fu.common.core.constant.UserConstants;
import com.xdhl.fu.common.core.domain.R;
import com.xdhl.fu.common.core.utils.JwtUtils;
import com.xdhl.fu.common.core.utils.StringUtils;
import com.xdhl.fu.common.core.web.domain.AjaxResult;
import com.xdhl.fu.common.redis.service.RedisService;
import com.xdhl.fu.common.security.auth.AuthUtil;
import com.xdhl.fu.common.security.service.TokenService;
import com.xdhl.fu.common.security.utils.SecurityUtils;
import com.xdhl.fu.member.domain.ChangeEmailBody;
import com.xdhl.fu.member.domain.MemberBasic;
import com.xdhl.fu.member.domain.vo.MemberBasicVO;
import com.xdhl.fu.member.form.LoginBody;
import com.xdhl.fu.member.form.RegisterBody;
import com.xdhl.fu.member.service.IMemberAuthService;
import com.xdhl.fu.member.service.IMemberBasicService;
import com.xdhl.fu.member.service.impl.EmailServiceImpl;
import com.xdhl.fu.member.service.impl.MemberTokenServiceImpl;
import com.xdhl.fu.system.api.model.LoginUser;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;

/**
 * 会员token 控制
 *
 * @author 朱力维
 * @time 2022/6/6 10:20
 */
@RestController
public class MemberAuthController {
    @Resource
    private TokenService tokenService;

    @Resource
    private IMemberAuthService memAuthService;

    @Resource
    private MemberTokenServiceImpl memberTokenService;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private EmailServiceImpl emailService;

    @Resource
    private RedisService redisService;

    @Resource
    private IMemberBasicService memberBasicService;

    private final static String EMAIL_PREFIX = CacheConstants.EMAIL_PREFIX;

    /**
     * 会员注册
     *
     * @param registerBody 会员注册信息
     * @return 注册结果
     */
    @PostMapping("/register")
    public R<?> register(@RequestBody RegisterBody registerBody) {
        MemberBasicVO memberBasicVO = memAuthService.register(registerBody);
        return R.ok(memberTokenService.createToken(memberBasicVO, memberBasicVO.getEmail()), "注册成功");
    }

    /**
     * 会员登录
     */
    @PostMapping("/login")
    public R<?> login(@RequestBody LoginBody form) {
        MemberBasicVO memberInfo = memAuthService.login(form.getUsername(), form.getPassword());
        // 获取登录token
        return R.ok(memberTokenService.createToken(memberInfo, form.getUsername()), "登录成功");
    }

    /**
     * 会员邮箱验证码登录
     */
    @PostMapping("/loginByEmail")
    public R<?> loginByEmail(@RequestBody LoginBody form) {
        MemberBasicVO memberInfo = memAuthService.loginByEmail(form.getEmail(), form.getAuthCode());
        // 获取登录token
        return R.ok(memberTokenService.createToken(memberInfo, form.getEmail()), "登录成功");
    }

    /**
     * 原邮箱验证码校验
     */
    @PutMapping("/verifyAuthCode")
    public R<?> verifyAuthCode(@RequestBody ChangeEmailBody changeEmailBody) {
        // 原邮箱验证码校验
        String authCode = stringRedisTemplate.opsForValue().get(CacheConstants.EMAIL_PREFIX + changeEmailBody.getOldEmail());
        if (StringUtils.isBlank(changeEmailBody.getInputAuthCode())) {
            return R.fail("邮箱验证码不能为空");
        }
        if (changeEmailBody.getInputAuthCode().equals(authCode)) {
            return R.ok();
        }
        return R.fail("邮箱验证码错误/失效");
    }

    /**
     * 邮箱更换
     */
    @PutMapping("/changeEmail")
    public R<?> changeEmail(@RequestBody ChangeEmailBody changeEmailBody) {
        LambdaQueryWrapper<MemberBasic> lqw = new LambdaQueryWrapper<>();
        lqw.eq(MemberBasic::getEmail, changeEmailBody.getOldEmail());
        MemberBasic memberBasic = memberBasicService.getOne(lqw);
        if (StringUtils.isAnyBlank(changeEmailBody.getInputAuthCode(), changeEmailBody.getNewEmail())) {
            return R.fail("邮箱/验证码不能为空");
        }
        LambdaQueryWrapper<MemberBasic> condition = new LambdaQueryWrapper<>();
        condition.eq(MemberBasic::getEmail, changeEmailBody.getNewEmail());
        MemberBasic member = memberBasicService.getOne(condition);
        if (null != member) {
            return R.fail("该邮箱已被注册");
        }
        // 新邮箱验证码校验
        String authCode = stringRedisTemplate.opsForValue().get(CacheConstants.EMAIL_PREFIX + changeEmailBody.getNewEmail());
        if (changeEmailBody.getInputAuthCode().equals(authCode)) {
            memberBasic.setEmail(changeEmailBody.getNewEmail());
            memberBasicService.updateById(memberBasic);
            return R.ok(null, "邮箱更换成功。");
        }
        return R.fail("邮箱验证码错误/失效");
    }

    /**
     * 退出登录
     */
    @DeleteMapping("/logout")
    public R<?> logout() {
        String token = SecurityUtils.getToken();
        if (StringUtils.isNotEmpty(token)) {
            String username = JwtUtils.getUserName(token);
            // 删除用户缓存记录
            AuthUtil.logoutByToken(token);
            // 记录用户退出日志
            memAuthService.logout(username);
        }
        return R.ok(null, "退出成功");
    }

    /**
     * 发送邮箱验证码
     */
    @GetMapping(value = {"/sendEmailAuthCode/{email}", "/sendEmailAuthCode"})
    public R<?> getAuthCode(@PathVariable(value = "email", required = false) String email) {
        if (StringUtils.isBlank(email)) {
            return R.fail(null, "邮箱不能为空");
        }
        if (!Pattern.matches(UserConstants.EMAIL_CHECK, email)) {
            return R.fail(null, "请输入正确的邮箱地址");
        }
        if (StringUtils.isNotBlank(stringRedisTemplate.opsForValue().get(getEmailAuthCodeRecordKey(email)))) {
            return R.fail(null, "一分钟内不能重复发送验证码");
        } else {
            String emailAuthCode = emailService.send(email);
            stringRedisTemplate.opsForValue().set(EMAIL_PREFIX + email, emailAuthCode, 5, TimeUnit.MINUTES);
            stringRedisTemplate.opsForValue().set(getEmailAuthCodeRecordKey(email), getEmailAuthCodeRecordKey(email), 1, TimeUnit.MINUTES);
            return R.ok(null, "邮箱验证码发送成功");
        }
    }

    /**
     * refreshToken刷新token令牌
     */
    @PostMapping("/refresh")
    public R<?> refresh(HttpServletRequest request) {
        LoginUser loginUser = tokenService.getLoginUser(request);
        if (StringUtils.isNotNull(loginUser)) {
            // 刷新令牌有效期
            tokenService.refreshToken(loginUser);
            return R.ok();
        }
        return R.ok();
    }

    /**
     * 获取登录会员信息
     */
    @GetMapping("/getMemberInfo")
    public R<?> getInfo() {
        return R.ok(memAuthService.getInfo(), "查询成功");
    }

    /**
     * 会员修改信息
     */
    @Transactional
    @PutMapping("/update")
    public AjaxResult edit(@RequestBody MemberBasic memberBasic) {
        String username = SecurityUtils.getUsername();
        MemberBasic data = memberBasicService.getByUsername(username);

        if (StringUtils.isBlank(memberBasic.getFirstNameCn())) {
            return AjaxResult.error("中文姓不能为空");
        } else {
            data.setFirstNameCn(memberBasic.getFirstNameCn());
        }

        if (StringUtils.isBlank(memberBasic.getLastNameCn())) {
            return AjaxResult.error("中文名不能为空");
        } else {
            data.setLastNameCn(memberBasic.getLastNameCn());
        }

        if (StringUtils.isBlank(memberBasic.getFirstNameEn())) {
            return AjaxResult.error("英文姓不能为空");
        } else {
            data.setFirstNameEn(memberBasic.getFirstNameEn());
        }

        if (StringUtils.isBlank(memberBasic.getLastNameEn())) {
            return AjaxResult.error("英文名不能为空");
        } else {
            data.setLastNameEn(memberBasic.getLastNameEn());
        }

        if (StringUtils.isBlank(memberBasic.getOccupationClass())) {
            return AjaxResult.error("职业不能为空");
        } else {
            data.setOccupationClass(memberBasic.getOccupationClass());
        }

        if (StringUtils.isBlank(memberBasic.getIdType())) {
            return AjaxResult.error("证件类型不能为空");
        } else {
            data.setIdType(memberBasic.getIdType());
        }

        if (StringUtils.isBlank(memberBasic.getIdCardNumber())) {
            return AjaxResult.error("证件号码不能为空");
        } else {
            data.setIdCardNumber(memberBasic.getIdCardNumber());
        }

        if (null == memberBasic.getIdDueDate()) {
            return AjaxResult.error("证件有效期不能为空");
        } else {
            data.setIdDueDate(memberBasic.getIdDueDate());
        }

        if (StringUtils.isBlank(memberBasic.getTelephoneNumber())) {
            return AjaxResult.error("手机号不能为空");
        } else {
            data.setTelephoneNumber(memberBasic.getTelephoneNumber());
        }

        if (memberBasicService.updateById(data))
            return AjaxResult.success("修改成功");
        else
            return AjaxResult.error("修改失败");
    }

    /**
     * 获取邮箱验证码发送记录缓存前缀
     *
     * @param email 邮箱
     * @return 邮箱验证码缓存前缀
     */
    private String getEmailAuthCodeRecordKey(String email) {
        return "email_authcode_record:" + email;
    }


}




